package bsh.meta;

import java.util.Map;

import org.objectweb.asm.Label;
import org.objectweb.asm.MethodVisitor;

import bsh.LocalVariable;
import bsh.TypeResolver;
import bsh.asm.acessor.ObjectAccessor;
import bsh.compilation.CompilationOptions;

/**
 * Representa um escopo, tipicamente um bloco delimitado por {}
 * 
 * @author takeshi
 */
public interface Scope extends TypeResolver {
    /**
     * Devolve uma variavel local com o nome passado visivel deste escopo
     * 
     * @param name String
     * @return {@link LocalVariable}
     */
    LocalVariable getVariable(String name);

    /**
     * Adiciona um ObjectAccessor a este escopo
     * 
     * @param name String
     * @param accessor Object
     */
    void addAccessor(String name, ObjectAccessor accessor);

    /**
     * Devolve um ObjectAccessor visivel a este escopo. Pode ou nao ser uma variavel local
     * 
     * @param name String
     * @return {@link ObjectAccessor}
     */
    ObjectAccessor getAccessor(String name);

    /**
     * Returns a map of all visible {@link ObjectAccessor}'s
     * 
     * @return {@link Map}
     */
    Map<String, ObjectAccessor> allVisibleAccessors();

    /**
     * Adiciona um parametro para este metodo.
     * 
     * @param name String
     * @param type {@link TypeWrapper}
     * @return {@link LocalVariable}
     */
    LocalVariable addMethodParameter(String name, TypeWrapper type);

    /**
     * Adiciona uma variavel local com escopo menor do que este escopo
     * 
     * @param name String
     * @param start Label
     * @param type o tipo
     * @return {@link LocalVariable}
     */
    LocalVariable addLocalVariable(String name, Label start, TypeWrapper type);

    /**
     * @return devolve o escopo global
     */
    Scope getRootScope();

    /**
     * @return o label de comeco deste escopo
     */
    Label getStartLabel();

    /**
     * @return o label de final deste escopo
     */
    Label getEndLabel();

    /**
     * Instala o label de inicio deste escopo
     * 
     * @param visitor {@link MethodVisitor}
     * @param options opcoes de compilacao
     */
    void installStartLabel(MethodVisitor visitor, CompilationOptions options);

    /**
     * Instala o label de final deste escopo. Se o {@link #getType()} for {@link ScopeType#METHOD}, opcionalmente instala definicoes sobre
     * as variaveis locais
     * 
     * @param visitor {@link MethodVisitor}
     * @param options {@link CompilationOptions}
     */
    void installEndLabel(MethodVisitor visitor, CompilationOptions options);

    /**
     * @return o tipo deste escopo
     */
    ScopeType getType();

    /**
     * @param offset int
     */
    void increaseOffset(int offset);

    /**
     * @return int
     */
    int getOffset();

    /**
     * @param lv {@link LocalVariable}
     */
    void registerVariable(LocalVariable lv);

    /**
     * @return true if this is a static scope - if the local variable 0 does not represent 'this'
     */
    boolean isStaticScope();

    /**
     * Returns the current method scope. May not be this scope, but is a parent of this scope
     * 
     * @return {@link MethodScope}
     */
    MethodScope currentMethod();

    /**
     * @return boolean
     */
    boolean isInsideConstructor();
}
